﻿#include "StdAfx.h"
#include "keyboard.h"

keyboard::keyboard()
{
	//Initialize the string
    this->input_str = L"";
	this->key_event = NULL;
	this->max_length = 255;
	//Enable Unicode //항상 활성화가 되는게 아니어서 배제함
	/*
	while(this->unicode_input == 0 || this->unicode_input -1)
		this->unicode_input = SDL_EnableUNICODE( SDL_ENABLE );
	*/
}
bool keyboard::init(SDL_Event * event)
{
	bool flag = false;
	if(event == NULL)
		flag = false;
	else{
		this->key_event = event;
		flag = true;
	}
	
	while(this->unicode_input == 0 || this->unicode_input -1)
		this->unicode_input = SDL_EnableUNICODE( SDL_ENABLE );

	return flag;
}
std::wstring keyboard::get_input_string()
{
	return this->input_str;
}
keyboard::~keyboard(void)
{
	//Disable Unicode
    //SDL_EnableUNICODE( SDL_DISABLE );
}

void keyboard::get_input()
{

	//키가눌러졌는지 체크
	if( this->key_event->type == SDL_KEYDOWN ){
		//지역변수에 지금 입력문자열을 할당
		std::wstring str = get_input_string();

		/////////////////////////////////////////////////////////////////////////////////
		// 문제 가능성이 있는 코드 
		// 유니코드가 활성화 되지 않는 문제로 
		// 쉬프트 입력과 같이 타이핑하는 경우를 처리 하지 못해서
		// 유니코드를 강제로 활성화 시킴
		/////////////////////////////////////////////////////////////////////////////////
		//강제로 활성 될때까지 루프
		while(	!SDL_EnableUNICODE( SDL_ENABLE ));
		//유니코드가 활성화 될때만 진행함
		Uint16 key_input = this->key_event->key.keysym.unicode;
		/////////////////////////////////////////////////////////////////////////////////
		//최대 입력값보다 많은지 체크
		if(str.length() <= get_maxlength()){
			//입력이 한영변환일때			
			if(key_input == (Uint16)'`')
				this->change_eh = this->change_eh * (-1);
			//입력이 스페이스일때
            else if( key_input == (Uint16)' ' )
                str += key_input;
			//입력이 숫자일때
			else if( ( key_input >= (Uint16)'0' ) && ( key_input <= (Uint16)'9' ) )
				str += key_input;
			//If backspace was pressed and the string isn't blank
			else if( ( key_input == SDLK_BACKSPACE ) && ( str.length() != 0 ) ){
				//Remove a character from the end
				str.erase( str.length() - 1 );
			}
			//입력이 영문일때(토글키로 구분)
			else if(get_enghan() == true)
			{

					//입력이 대문자일때
					if( ( key_input >= (Uint16)'A' ) && ( key_input <= (Uint16)'Z' ) )
						str += key_input;
					//입력이 소문자일때
					else if( ( key_input >= (Uint16)'a' ) && ( key_input <= (Uint16)'z' ) )
						str += key_input;	
			}
			//입력이 한글일때 처리
			else if(get_enghan() == false)
			{
				//입력된 영문자와 소문자를 각각 키보드의 한글각인으로 매핑 결과는 유니코드 호환 자모가 됨
				//유니코드 호환 자모만 한글 자모 상태로 출력가능(폰트 문제인지 SDL문제인지 파악못함)
				if((( key_input >= (Uint16)'A' ) && ( key_input <= (Uint16)'Z' )) || (( key_input >= (Uint16)'a' ) && ( key_input <= (Uint16)'z' )))
				{
					str += abc_to_compatibility_koran_jamo(key_input);
					
					//<한글조합처리> 입력된 글자들이 한 글자 이상일때
					if(str.length() > 1)
					{
						//입력된 글자가 앞글자와 합쳐짐여부 체크 (true로 합쳐짐-즉 뒷글자가 삭제됨)
						bool combine = true;
						std::wstring first;
						std::wstring last;	
						first = str[str.length() -2]; //first 에 앞글자 할당
						last = str[str.length() -1]; //last 에 현재 입력글자 할당
						//앞글자가 호환 한글자모이거나 완성형 한글일때 조합처리함
						if((first[0] >= 0x3131 && first[0] <= 0x3163) ||  //한글 호환자모 코드범위
							(first[0] >= 0xAC00 && first[0] <= 0xD7A3)) //완성형 한글 코드범위
						{
							//완성형 유니코드로 분해하고 다시 합칠때 한글 호환 자모가 아닌 한글 자모가 필요하다.
							//그러므로 입력값 first와 last가 각각 호환자모로 되어있다면 한글 자모로 변환해주어야 한다.
							if(first[0] >= 0x3131 && first[0] <= 0x3163)
								first = compatibility_to_normal_jamo(first);
							if(last[0] >= 0x3131 && last[0] <= 0x3163)
								last = compatibility_to_normal_jamo(last);

							//초성, 중성 종성으로 분해한 값을 보관(에러 파악을 위해 기본값을 9999로 넣는다. 
							//앞글자의 초, 중, 종성값
							int cho = 9999;
							int jung = 9999;
							int jong = 9999;
							//뒷글자  초, 중성값 -초성 입력일 수도 중성 입력일 수도 있으므로 둘다 넣어둠
							int l_cho  =9999;
							int l_jung =9999;

							//조건1 앞글자가 자음이고 뒷글자가 모음인 경우 
							if((first[0] >= 0x1010) && (first[0] <= 0x1112)&& (last[0] >= 0x1161) && (last[0] <= 0x1175)){
								cho = first[0] - 0x1100;
								jung = last[0] - 0x1161;
								jong = 0;
							}
							else if(first[0] >= 0xAC00 && first[0] <= 0xD7A3) //완성형인경우
							{
								//우선 완성형을 분리함
								cho  = (first[0] - 0xAC00) / (21 * 28);
								jung = ((first[0] - 0xAC00) % (21 * 28)) / 28;
								jong = (first[0] - 0xAC00) % 28;

								//완성형이기 때문에 초성과 중성은 갖고 있으나
								//중성과 종성이 더해질 수 있으며
								//이후 입력글자에 따라 종성이 이탈할수 있다. 

								//뒷글자가 모음인 경우 
								if(last[0] >= 0x1161 && last[0] <= 0x1175){
									//중성이 더해지는지 체크 (ㅗ ㅜ ㅡ 일때 더해짐)
									if( jong == 0) //종성이 없을때만 더함
										switch(jung){
											case 8:{ //ㅗ{
												switch(last[0]){
													case 0x1161:	jung += 1; break;
													case 0x1162: jung += 2; break;
													case 0x1175: jung += 3; break;
													default: combine= false; break;
												}
												break;
											}
											case 13: {//ㅜ
												switch(last[0]){
													case 0x1165: jung += 1; break;
													case 0x1166: jung += 2; break;
													case 0x1175: jung += 3; break;
													default: combine = false; break;
												}
												break;
											}
											default:
												if(jung == 18 && last[0] == 0x1175)
													jung += 1; 
												else
													combine = false;
										}
									else combine = false;

									if(combine == false){
										//합쳐지지 않는 경우
										//그대로 중성에 입력
										l_jung = last[0] - 0x1161;

										//종성이 있는 경우 가져옴
										if(jong > 0){
											l_cho = jong_to_cho(jong);
											//남는 종성 체크
											jong = remain_jong(jong+0x11A7);				
										}
									}								
								}
								//뒷글자가 자음인 경우 
								else if(last[0] >= 0x1010 && last[0] <= 0x1112)
								{
									switch(jong) {
										case 0: {//종성이 없는 경우 초성으로 종성을 함
											switch(last[0]){ //종성으로 쓸 수 없는 초성 구분
												case 0x1104: //ㄸ
												case 0x1108: //ㅃ
												case 0x110D: //ㅉ
													combine = false;
													l_cho = last[0];
													break;
												default:
													jong = cho_to_jong(last[0]) -0x11A7; break;
											}
											break;
										}
										//합치는게 가능한 종성 체크 
										case 1: {//ㄱ
											if(last[0] == 0x1109) //ㅅ
												jong += 1;
											else
											{
												combine = false;
												l_cho = last[0];
											}
											break; //ㄳ
										}
										case 4:{ //ㄴ
											switch(last[0]) {
												case 4364:{jong += 1; break;} //ㄵ
												case 4370:{jong += 2; break;} //ㄶ
												default: 
													combine = false;
													l_cho = last[0];
											}
											break;
										}
										case 8:{ //ㄹ
											switch(last[0]){ //ㄹ
												case 4352:{jong += 1; break;} //ㄺ
												case 4358:{jong += 2; break;} //ㄻ
												case 4359:{jong += 3; break;} //ㄼ
												case 4361:{jong += 4; break;} //ㄽ
												case 4368:{jong += 5; break;} //ㄾ
												case 4369:{jong += 6; break;} //ㄿ
												case 4370:{jong += 7; break;} //ㅀ
												default: 
													combine = false;
													l_cho = last[0];

											}
											break;
										}
										case 17:{
											if((jong == 17) && last[0] == 4361)
											{
												jong += 1; 
												break; //ㅄ
											}
											else;

										}
										default: //합쳐지지 않는 자음
											combine = false;
											l_cho = last[0];
									}
								}
								/* 디버그중-- 일단 주석처리
								cho  = (first[0] - 0xAC00) / (21 * 28);
								jung = ((first[0] - 0xAC00) % (21 * 28)) / 28;
								jong = (first[0] - 0xAC00) % 28;
								*/
							}


								//합치기
								//앞문자
								if((cho != 9999) && (jung != 9999))
									str[str.length() -2] =  0xAC00 + (cho * 21 * 28) + (jung * 28) + jong;
								else
									combine = false; //앞문자가 완성형이 아니므로 합쳐지지 않았음
								//뒷문자
								if(combine == false)
									if((l_cho != 9999) && (l_jung != 9999))
										str[str.length() -1] =  0xAC00 + (l_cho * 21 * 28) + (l_jung * 28);
									else
										str[str.length() -1] = (normal_jamo_to_compatibility(last))[0];
								else
									str.erase( str.length() - 1 );
							
						} //앞글자가 조합이나 완성형 한글일때
					} //글자 길이 확인 1글자이상일때 
				} //한글처리 
			}
			this->input_str = str;
		}
	}
}

int keyboard::cho_to_jong(int in_cho)
{
	int jong = 9999;
	switch(in_cho)
	{
		case 0x1100:{ jong = 0x11A8; break; } //ㄱ
		case 0x1102: { jong = 0x11AB; break;} //ㄴ
		case 0x1103:{ jong = 0x11AE; break;} //ㄷ
		case 0x1105:{ jong = 0x11AF; break;} //ㄹ 
		case 0x1106:{ jong = 0x11B7; break;} //ㅁ
		case 0x1107:{ jong = 0x11B8; break;} //ㅂ
		case 0x1109:{ jong = 0x11BA; break;} //ㅅ
		case 0x110B:{ jong = 0x11BC; break;} //ㅇ
		case 0x110C:{ jong = 0x11BD; break;} //ㅈ
		case 0x110E:{ jong = 0x11BE; break;} //ㅊ
		case 0x110F:{ jong = 0x11BF; break;} //ㅋ
		case 0x1110:{ jong = 0x11C0; break;} //ㅌ
		case 0x1111:{ jong = 0x11C1; break;} //ㅍ
		case 0x1112:{ jong = 0x11C2; break;} //ㅎ
	}
	return jong;
}
int keyboard::remain_jong(int in_jong)
{
	int jong =0;
	switch(in_jong)
	{
	case 0x11AA: jong = 0x11AF-0x11A7; break; //ㄳ
	case 0x11AC: //ㄵ
	case 0x11AD: jong = 0x11AB-0x11A7; break; //ㄶ
	case 0x11B0: //ㄺ
	case 0x11B1: //ㄻ
	case 0x11B2: //ㄼ
	case 0x11B3: //ㄽ
	case 0x11B4: //ㄾ
	case 0x11B5: //ㄿ
	case 0x11B6: jong = 0x11AF-0x11A7; break; //ㅀ
	case 0x11B9: jong = 0x11B8-0x11A7; break; //ㅄ
	default:
		jong = 0;
	}
	return jong;
}
int keyboard::jong_to_cho(int in_jong)
{
	int cho =0;
	switch(in_jong)
	{
		case 1: //ㄱ
		case 9:{ //ㄺ
			cho = 0; //ㄱ
			break;}
		case 4:{ //ㄴ
			cho = 2;
			break;}
		case 7:{ //ㄷ
			cho = 3;
			break;}
		case 8:{//ㄹ
			cho = 5;
			break;}
		case 16: //ㅁ
		case 10:{//ㄻ
			cho = 6;
			break;}
		case 17: //ㅂ
		case 11:{ //ㄼ
			cho = 7;
			break;}
		case 3: //ㄳ
		case 12: //ㄽ
		case 19:  //ㅅ
		case 18:{ //ㅄ
			cho = 9;
			break;}
		case 21:{ //ㅇ
			cho = 11;
			break;}
		case 22: //ㅈ
		case 5:{ //ㄵ
			cho = 12;
			break;}
		case 23:{ //ㅊ
			cho = 14;
			break;}
		case 24:{ //ㅋ
			cho = 15;
			break;}
		case 25: //ㅌ 
		case 13:{ //ㄾ
			cho = 16;
			break;}
		case 26: 
		case 14:{ 
			cho = 17;
			break;}
		case 27: //ㅎ
		case 15: //ㅀ
		case 6:{ //ㄶ
			cho = 18;
			break;}
	}
	return cho;
}
std::wstring keyboard::normal_jamo_to_compatibility(std::wstring input_key)
{
	std::wstring character;
	switch(input_key[0])
	{
		//유니코드 한글자모 
		//http://www.unicode.org/charts/PDF/U1100.pdf
		case 0x1100: character += L'ㄱ'; break;
		case 0x1101: character += L'ㄲ'; break;
		case 0x1102: character += L'ㄴ'; break;
		case 0x1103: character += L'ㄷ'; break;
		case 0x1104: character += L'ㄸ'; break;
		case 0x1105: character += L'ㄹ'; break;
		case 0x1106: character += L'ㅁ'; break;
		case 0x1107: character += L'ㅂ'; break;
		case 0x1108: character += L'ㅃ'; break;
		case 0x1109: character += L'ㅅ'; break;
		case 0x110A: character += L'ㅆ'; break;
		case 0x110B: character += L'ㅇ'; break;
		case 0x110C: character += L'ㅈ'; break;
		case 0x110D: character += L'ㅉ'; break;
		case 0x110E: character += L'ㅊ'; break;
		case 0x110F: character += L'ㅋ'; break;
		case 0x1110: character += L'ㅌ'; break;
		case 0x1111: character += L'ㅍ'; break;
		case 0x1112: character += L'ㅎ'; break;
		case 0x1161: character += L'ㅏ'; break;
		case 0x1162: character += L'ㅐ'; break;
		case 0x1163: character += L'ㅑ'; break;
		case 0x1164: character += L'ㅒ'; break;
		case 0x1165: character += L'ㅓ'; break;
		case 0x1166: character += L'ㅔ'; break;
		case 0x1167: character += L'ㅕ'; break;
		case 0x1168: character += L'ㅖ'; break;
		case 0x1169: character += L'ㅗ'; break;
		case 0x116D: character += L'ㅛ'; break;
		case 0x116E: character += L'ㅜ'; break;
		case 0x1172: character += L'ㅠ'; break;
		case 0x1173: character += L'ㅡ'; break;
		case 0x1175: character += L'ㅣ'; break;

		default:
			character += L"에러발생:compatibility_to_normal_jamo";
	}
	return character;
}
std::wstring keyboard::compatibility_to_normal_jamo(std::wstring input_key)
{
	std::wstring character;
	switch(input_key[0])
	{
		//유니코드 한글자모 
		//http://www.unicode.org/charts/PDF/U1100.pdf
		case L'ㅁ': character += 4358;break; //ㅁ
		case L'ㅠ': character += 4466;break; //ㅠ
		case L'ㅊ': character += 4366;break; //ㅊ
		case L'ㅇ': character += 4363;break; //ㅇ
		case L'ㄷ': character += 4355;break; //ㄷ
		case L'ㄹ': character += 4357;break; //ㄹ
		case L'ㅎ': character += 4370;break; //ㅎ
		case L'ㅂ': character += 4359;break; //ㅂ
		case L'ㄱ': character += 4352;break; //ㄱ
		case L'ㄴ': character += 4354;break; //ㄴ
		case L'ㅅ': character += 4361;break; //ㅅ
		case L'ㅕ': character += 4455;break; //ㅕ
		case L'ㅍ': character += 4369;break; //ㅍ
		case L'ㅈ': character += 4364;break; //ㅈ
		case L'ㅌ': character += 4368;break; //ㅌ
		case L'ㅛ': character += 4461;break; //ㅛ
		case L'ㅋ': character += 4367;break; //ㅋ
		case L'ㅗ': character += 4457;break; //ㅗ
		case L'ㅑ': character += 4451;break; //ㅑ
		case L'ㅓ': character += 4453;break; //ㅓ
		case L'ㅏ': character += 4449;break; //ㅏ
		case L'ㅣ': character += 4469;break; //ㅣ
		case L'ㅡ': character += 4467;break; //ㅡ
		case L'ㅜ': character += 4462;break; //ㅜ
		case L'ㅐ': character += 4450;break; //ㅐ
		case L'ㅔ': character += 4454;break; //ㅔ
		case L'ㅒ': character += 4452;break; 
		case L'ㅖ': character += 4456;break;
		case L'ㅃ': character += 4360;break;
		case L'ㄲ': character += 4353;break;
		case L'ㄸ': character += 4356;break;
		case L'ㅉ': character += 4365;break;
		case L'ㅆ': character += 4362;break;
		default:
			character += L"에러발생:compatibility_to_normal_jamo";
	}

	return character;
}
std::wstring keyboard::abc_to_compatibility_koran_jamo(Uint16 input_key)
{
	std::wstring str;
	switch(input_key)
	{
		//대문자 입력영역
		//http://www.unicode.org/charts/PDF/U3130.pdf
		case (Uint16)'A':{	str += L'ㅁ'; break;} //유니코드 한글 호환 자모
		case (Uint16)'B':{	str += L'ㅠ'; break;}
		case (Uint16)'C':{	str += L'ㅊ'; break;}
		case (Uint16)'D':{	str += L'ㅇ'; break;}
		case (Uint16)'E':{	str += L'ㄸ'; break;}
		case (Uint16)'F':{	str += L'ㄹ'; break;}
		case (Uint16)'G':{	str += L'ㅎ'; break;}
		case (Uint16)'H':{	str += L'ㅗ'; break;}
		case (Uint16)'I':{	str += L'ㅑ'; break;}
		case (Uint16)'J':{	str += L'ㅓ'; break;}
		case (Uint16)'K':{	str += L'ㅏ'; break;}
		case (Uint16)'L':{	str += L'ㅣ'; break;}
		case (Uint16)'M':{	str += L'ㅡ'; break;}
		case (Uint16)'N':{	str += L'ㅜ'; break;}
		case (Uint16)'O':{	str += L'ㅒ'; break;}
		case (Uint16)'P':{	str += L'ㅖ'; break;}
		case (Uint16)'Q':{	str += L'ㅃ'; break;}
		case (Uint16)'R':{	str += L'ㄲ'; break;}
		case (Uint16)'S':{	str += L'ㄴ'; break;}
		case (Uint16)'T':{	str += L'ㅆ'; break;}
		case (Uint16)'U':{	str += L'ㅕ'; break;}
		case (Uint16)'V':{	str += L'ㅍ'; break;}
		case (Uint16)'W':{	str += L'ㅉ'; break;}
		case (Uint16)'X':{	str += L'ㅌ'; break;}
		case (Uint16)'Y':{	str += L'ㅛ'; break;}
		case (Uint16)'Z':{	str += L'ㅋ'; break;}
		//소문자 입력영역
		case (Uint16)'a':{ str += L'ㅁ';break;} //ㅁ
		case (Uint16)'b':{ str += L'ㅠ';break;} //ㅠ
		case (Uint16)'c':{ str += L'ㅊ';break;} //ㅊ
		case (Uint16)'d':{ str += L'ㅇ';break;} //ㅇ
		case (Uint16)'e':{ str += L'ㄷ';break;} //ㄷ
		case (Uint16)'f':{ str += L'ㄹ';break;} //ㄹ
		case (Uint16)'g':{ str += L'ㅎ';break;} //ㅎ
		case (Uint16)'h':{ str += L'ㅗ';break;} //ㅗ
		case (Uint16)'i':{ str += L'ㅑ';break;} //ㅑ
		case (Uint16)'j':{ str += L'ㅓ';break;} //ㅓ
		case (Uint16)'k':{ str += L'ㅏ';break;} //ㅏ
		case (Uint16)'l':{ str += L'ㅣ';break;} //ㅣ
		case (Uint16)'m':{ str += L'ㅡ';break;} //ㅡ
		case (Uint16)'n':{ str += L'ㅜ';break;} //ㅜ
		case (Uint16)'o':{ str += L'ㅐ';break;} //ㅐ
		case (Uint16)'p':{ str += L'ㅔ';break;} //ㅔ
		case (Uint16)'q':{ str += L'ㅂ';break;} //ㅂ
		case (Uint16)'r':{ str += L'ㄱ';break;} //ㄱ
		case (Uint16)'s':{ str += L'ㄴ';break;} //ㄴ
		case (Uint16)'t':{ str += L'ㅅ';break;} //ㅅ
		case (Uint16)'u':{ str += L'ㅕ';break;} //ㅕ
		case (Uint16)'v':{ str += L'ㅍ';break;} //ㅍ
		case (Uint16)'w':{ str += L'ㅈ';break;} //ㅈ
		case (Uint16)'x':{ str += L'ㅌ';break;} //ㅌ
		case (Uint16)'y':{ str += L'ㅛ';break;} //ㅛ
		case (Uint16)'z':{ str += L'ㅋ';break;} //ㅋ
		default:
			str += L"에러발생:abc_to_compatibility_koran_jamo";
	}

	return str;
}
void keyboard::clear()
{
	this->input_str = L"";
}

bool keyboard::get_enghan()
{
	bool flag = true;
	if(this->change_eh == 1)
		flag = true;
	else if(this->change_eh == -1)
		flag = false;
	else //예상범위 이외 값일 경우 영어로 초기화
		this->change_eh = 1;
	return flag;
}

unsigned int keyboard::get_maxlength()
{
	return this->max_length;
}
void keyboard::set_maxlength(int input_max)
{
	if(input_max >0)
		this->max_length = input_max;
	else //0이거나 0보다 작은 음수 입력에 대해 
		this->max_length = 0;
}